/*
 * @(#)AbstractWSClient.java
 * Date 2013-02-20
 * Version 1.0
 * Author Jim Horner
 * Copyright (c)2012
 */


package us.hornerscorners.lamppost.ws;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.xml.ws.Binding;
import javax.xml.ws.BindingProvider;

import javax.xml.ws.handler.Handler;

import org.apache.commons.lang3.ArrayUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import us.hornerscorners.lamppost.config.EndpointConfig;

import us.hornerscorners.lamppost.model.audit.AuditContext;


/**
 *
 * @author jim
 */
public abstract class AbstractWSClient implements IWSClient {

    /** Field description */
    private final EndpointConfig config;

    /** Field description */
    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * Constructs ...
     *
     *
     * @param config
     */
    public AbstractWSClient(EndpointConfig config) {

        super();
        this.config = config;
    }

    /**
     * Method description
     *
     *
     * @param auditContext
     * @param bprovider
     * @param handlers
     * @return 
     */
    protected AddressCallback configureBindingProvider(AuditContext auditContext,
            BindingProvider bprovider, Handler... handlers) {

        AddressCallback result = null;

        Map<String, Object> context = bprovider.getRequestContext();

        context.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY,
                    this.config.getUrl().toString());

        context.put("com.sun.xml.ws.request.timeout", this.config.getRequestTimeout());
        context.put("com.sun.xml.ws.connect.timeout", this.config.getConnectTimeout());

        Binding binding = bprovider.getBinding();
        List<Handler> handlerList = binding.getHandlerChain();

        if (handlerList == null) {
            handlerList = new ArrayList<>();
        }

        if (auditContext != null) {

            TransactionContext transContext = auditContext.getTransactionContext();

            if (transContext != null) {

                handlerList.add(new SOAPTransactionHandler(transContext));
            }

            result = new AddressCallback();
            handlerList.add(new SOAPAddressHandler(result));
        }

        if (ArrayUtils.isNotEmpty(handlers)) {

            handlerList.addAll(Arrays.asList(handlers));
        }

        if (this.config.isDebugMode()) {
            handlerList.add(new SOAPDebugHandler());
        }

        bprovider.getBinding().setHandlerChain(handlerList);

        return result;
    }

    /**
     * Method description
     *
     *
     * @return
     */
    @Override
    public String getClientId() {
        return this.config.getId();
    }

    /**
     * Method description
     *
     *
     * @return
     */
    @Override
    public EndpointConfig getConfig() {
        return config;
    }

    /**
     * Method description
     *
     *
     * @param auditContext
     * @param addressCallback
     *
     * @return
     */
    protected AuditContext parseOutgoingContext(AuditContext auditContext,
            AddressCallback addressCallback) {

        AddressContext addressContext = addressCallback.getOutgoingContext();

        if (addressContext == null) {

            logger.warn("AddressContext is null!!!!");
        }

        return new AuditContext(auditContext.getEventType(),
                                auditContext.getServiceConfig(),
                                auditContext.getTransactionContext(), addressContext);
    }
}
